﻿using System;
using System.Collections.Generic;
using System.Drawing;
using System.Text;
using System.Xml.Serialization;

namespace ExcelExportLib
{
    /// <summary>Cell style information</summary>
    [XmlRoot("Style")]
    public class ExcelCellStyle: IXmlSerializable
    {
        #region values
        /// <summary>ID of style </summary>
        public readonly string name;
        /// <summary>This property identifies this style as a named style that was created in Excel using the Style command (Format menu). Duplicate names are illegal. </summary>
        public string excelStyleName;

        /// <summary>Vertical text alignment in cell </summary>
        public eVerticalAlignment? vertical;
        /// <summary>Horizontal text alignment in cell </summary>
        public eHorizontalAlignment? horizontal;
        /// <summary>Wrap text or not</summary>
        public bool? wrapText;

         /// <summary>Number format in cell</summary>
        public string numberFormat;

        ///<summary>Background fill</summary>
        public Color? BacgroundColor;
        /// <summary>Specifies the fill pattern in the cell. The fill pattern determines how to blend the Color and PatternColor attributes to produce the cell's appearance. </summary>
        public eBackgroundPattern BackgroundPattern;
        public Color? BackgroundPatternColor;

        public ExcelCellStyleFont Font = new ExcelCellStyleFont();

        /// <summary>Name of parent style</summary>
        public string parent_style;

        /// <summary>Array of cell borders </summary>
        public Dictionary<eBorderPosition, ExcelCellStyleBorder> borders = new Dictionary<eBorderPosition, ExcelCellStyleBorder>();
        /// <summary>Flag indicating how many times style is actually used in document </summary>
        public int TimesUsed = 0;
        #endregion


        #region static values and functions

        /// <summary>Array of defined styles and names </summary>
        public static Dictionary<string, ExcelCellStyle> styles = new Dictionary<string, ExcelCellStyle>();
        /// <summary>Array of associations between cell types and styles names for each cell type </summary>
        public static Dictionary<eCellType, string> styleAssociation = new Dictionary<eCellType, string>();
  
        public static ExcelCellStyle AddCellStyle(string style_name)
        {
            ExcelCellStyle ecs = new ExcelCellStyle(style_name);
            styles[style_name] = ecs;
            //ecs.TimesUsed += 1;
            return ecs;
        }
        public static ExcelCellStyle AddCellStyle(string style_name, string parent_style_name)
        {
            ExcelCellStyle ecs = new ExcelCellStyle(style_name, parent_style_name);
            styles[style_name] = ecs;
           // ecs.TimesUsed += 1;
            return ecs;
        }

        public static string GetStyleForCellType(eCellType ect)
        {
            string style = "";
            if (styleAssociation.TryGetValue(ect, out style))
                return style;

            return null;
        }


        public static void CleanUpStyles(ExcelDocument WorkSheet)
        {
            int counter=1;
            string[] _StylesNotOk = { };
            System.Collections.Generic.IEnumerator<KeyValuePair<string, ExcelCellStyle>> _iterator;
            _iterator = ExcelCellStyle.styles.GetEnumerator();
            while (_iterator.MoveNext())
            {
                
                if (_iterator.Current.Value.TimesUsed<1)
                {
                    Array.Resize(ref _StylesNotOk, counter);
                    _StylesNotOk.SetValue(_iterator.Current.Key, counter - 1);
                    counter += 1;
                }
            }
            foreach (string Unused in _StylesNotOk)
            {
                ExcelCellStyle.styles.Remove(Unused); 
            }
        }
        #endregion


        #region Contructors

        /// <summary>Constructor for serialisation only!</summary>
        public ExcelCellStyle() {}

        /// <summary>initialises default cell styles </summary>
        static ExcelCellStyle()
        {
            ExcelCellStyle ecs = AddCellStyle("Default");
            ecs.excelStyleName = "Normal";
            ecs.vertical = eVerticalAlignment.Bottom;
            ecs.horizontal = eHorizontalAlignment.Justify;
            ecs.wrapText = false;
            ecs.Font.Name = "Arial";
            ecs.Font.Charset = 204;
            ecs.TimesUsed = 1;
            //ecs.BackgroundPattern = eBackgroundPattern.None;
            
            AddCellStyle("Date").numberFormat=@"dd/mm/yy;@";
            styleAssociation[eCellType.Date] = "Date";

            AddCellStyle("DateTime").numberFormat = @"dd/mm/yy\ h:mm;@";
            styleAssociation[eCellType.DateTime] = "DateTime";

            AddCellStyle("Time").numberFormat = @"h:mm;@";
            styleAssociation[eCellType.Time] = "Time";
        }

        public ExcelCellStyle(string name)
        {
            this.name = name;
        }

        public ExcelCellStyle(string name, string parent_style_name)
        {
            this.name = name;
            this.parent_style = parent_style_name;
        }

        #endregion

        /// <summary>Adds new border definition </summary>
        /// <param name="bPosition">position of border</param>
        /// <param name="bStyle">line style</param>
        /// <param name="bWeight">line weight (thickness)</param>
        /// <param name="bColor">line color</param>
        public ExcelCellStyleBorder AddBorder(eBorderPosition bPosition, eBorderStyle bStyle, eBorderWeight bWeight, Color bColor)
        {
            ExcelCellStyleBorder brd = new ExcelCellStyleBorder(bPosition, bStyle, bWeight, bColor);
            this.borders[bPosition] = brd;
            return brd;
        }


        #region IXmlSerializable Members

        public System.Xml.Schema.XmlSchema GetSchema()
        {
            return null;
        }

        public void ReadXml(System.Xml.XmlReader reader)
        {
            throw new NotImplementedException();
        }

        public void WriteXml(System.Xml.XmlWriter writer)
        {
            writer.WriteExcelAttribute("ID", name);
            writer.WriteExcelAttribute("Parent", parent_style);
            writer.WriteExcelAttribute("Name", excelStyleName);

            if ((vertical != null) || (horizontal != null) || (wrapText.HasValue))
            {
                writer.WriteStartElement("Alignment");
                writer.WriteExcelAttribute("Vertical", vertical); 
                writer.WriteExcelAttribute("Horizontal", horizontal);
                writer.WriteExcelAttribute("WrapText", wrapText);
                writer.WriteEndElement();
            }

            if (borders.Count >0 )
            {
                writer.WriteStartElement("Borders");

                foreach (ExcelCellStyleBorder brd in borders.Values)
                {
                    writer.WriteStartElement("Border");
                    brd.WriteXml(writer);
                    writer.WriteEndElement();
                }
                writer.WriteEndElement();
            }
            if (BacgroundColor != null)
            {
                writer.WriteStartElement("Interior");
                writer.WriteExcelAttribute("Color", BacgroundColor);
                writer.WriteExcelAttribute("Pattern", BackgroundPattern);
                writer.WriteExcelAttribute("PatternColor", BackgroundPatternColor);
                writer.WriteEndElement();
            }
            if (numberFormat != null)
            {
                writer.WriteStartElement("NumberFormat");
                writer.WriteExcelAttribute("Format", numberFormat);
                writer.WriteEndElement();
            }

            if (Font != null)
            {
                writer.WriteStartElement("Font");
                Font.WriteXml(writer);
                writer.WriteEndElement();

            }
        }

        #endregion
    }
}
